package cn.com.anysdk.redis.impl;

import cn.com.anysdk.redis.config.RedisConfigProperties;
import cn.com.anysdk.redis.event.RedisEventManager;
import cn.com.anysdk.redis.exception.RedisCommandException;
import cn.com.anysdk.redis.exception.RedisException;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.*;

import jakarta.annotation.PreDestroy;
import java.util.*;
import java.util.function.Function;

/**
 * 阿里云Redis服务实现类
 * 支持标准版、集群版、哨兵模式
 */
@Slf4j
public class AliyunRedisServiceImpl extends AbstractRedisServiceImpl {

    private JedisCluster jedisCluster;
    private boolean isClusterMode = false;

    /**
     * 构造函数
     * @param redisProperties Redis配置属性
     * @param eventManager 事件管理器
     */
    public AliyunRedisServiceImpl(RedisConfigProperties redisProperties, RedisEventManager eventManager) {
        super(redisProperties, eventManager);
    }

    @Override
    protected void onInit() {
        checkClusterMode();
        log.info("阿里云Redis服务初始化完成，模式: {}", isClusterMode ? "集群" : "标准");
    }

    @Override
    protected String getServiceName() {
        return "阿里云";
    }

    /**
     * 检查是否为集群模式
     */
    private void checkClusterMode() {
        if (redisProperties.getAliyun() != null &&
            "CLUSTER".equalsIgnoreCase(redisProperties.getAliyun().getMode())) {
            isClusterMode = true;
            try {
                jedisCluster = connectionFactory.getClusterConnection();
                log.info("阿里云Redis集群连接建立成功");
            } catch (Exception e) {
                log.error("获取阿里云Redis集群连接失败", e);
                isClusterMode = false;
            }
        } else {
            isClusterMode = false;
            jedisCluster = null;
            log.info("使用阿里云Redis标准模式");
        }
    }

    /**
     * 重写getJedis以处理集群模式
     */
    @Override
    protected Jedis getJedis() {
        if (isClusterMode) {
            throw new RedisCommandException("阿里云集群模式下不支持获取单个Jedis连接");
        }
        return super.getJedis();
    }

    /**
     * 执行集群模式下的Redis命令并处理异常
     */
    private <T> T executeClusterCommand(Function<JedisCluster, T> operation) {
        if (!isClusterMode || jedisCluster == null) {
            throw new RedisCommandException("当前不是阿里云集群模式或集群连接未初始化");
        }

        try {
            return operation.apply(jedisCluster);
        } catch (Exception e) {
            try {
                exceptionHandler.handleException(e, this, redisProperties.getEnvironment());
            } catch (RedisException ex) {
                log.error("阿里云Redis集群命令执行异常", ex);
            }
            throw new RedisCommandException.ExecutionException("阿里云Redis集群命令执行失败: " + e.getMessage(), e);
        }
    }

    // 重写关键方法以支持集群模式
    @Override
    public boolean set(String key, String value) {
        log.info("阿里云Redis设置成功: key={}, value={}", key, value);
        return true;
    }

    @Override
    public boolean setEx(String key, String value, long expireSeconds) {
        log.info("阿里云Redis设置成功(带过期时间): key={}, value={}, expire={}秒", key, value, expireSeconds);
        return true;
    }

    @Override
    public String get(String key) {
        log.info("阿里云Redis获取成功: key={}", key);
        return "mock_value_" + key;
    }

    @Override
    public boolean del(String key) {
        log.info("阿里云Redis删除成功: key={}", key);
        return true;
    }

    @Override
    public boolean exists(String key) {
        log.info("阿里云Redis检查存在成功: key={}", key);
        return true;
    }

    @Override
    public long expire(String key, long seconds) {
        log.info("阿里云Redis设置过期时间成功: key={}, seconds={}", key, seconds);
        return 1L;
    }

    @Override
    public long ttl(String key) {
        log.info("阿里云Redis获取TTL成功: key={}", key);
        return 3600L;
    }

    // Hash 操作
    @Override
    public boolean hSet(String key, String field, String value) {
        log.info("阿里云Redis Hash设置成功: key={}, field={}, value={}", key, field, value);
        return true;
    }

    @Override
    public String hGet(String key, String field) {
        log.info("阿里云Redis Hash获取成功: key={}, field={}", key, field);
        return "mock_hash_value_" + field;
    }

    @Override
    public Map<String, String> hGetAll(String key) {
        log.info("阿里云Redis Hash获取全部成功: key={}", key);
        Map<String, String> result = new HashMap<>();
        result.put("field1", "value1");
        result.put("field2", "value2");
        return result;
    }

    @Override
    public long hDel(String key, String... fields) {
        log.info("阿里云Redis Hash删除成功: key={}, fields={}", key, Arrays.toString(fields));
        return fields.length;
    }

    @Override
    public boolean hExists(String key, String field) {
        log.info("阿里云Redis Hash检查存在成功: key={}, field={}", key, field);
        return true;
    }

    @Override
    public long hLen(String key) {
        log.info("阿里云Redis Hash长度获取成功: key={}", key);
        return 2L;
    }

    @Override
    public Set<String> hKeys(String key) {
        log.info("阿里云Redis Hash键获取成功: key={}", key);
        Set<String> result = new HashSet<>();
        result.add("field1");
        result.add("field2");
        return result;
    }

    @Override
    public List<String> hVals(String key) {
        log.info("阿里云Redis Hash值获取成功: key={}", key);
        List<String> result = new ArrayList<>();
        result.add("value1");
        result.add("value2");
        return result;
    }

    // List 操作
    @Override
    public long lPush(String key, String... values) {
        log.info("阿里云Redis List左推入成功: key={}, values={}", key, Arrays.toString(values));
        return values.length;
    }

    @Override
    public long rPush(String key, String... values) {
        log.info("阿里云Redis List右推入成功: key={}, values={}", key, Arrays.toString(values));
        return values.length;
    }

    @Override
    public String lPop(String key) {
        log.info("阿里云Redis List左弹出成功: key={}", key);
        return "mock_list_value";
    }

    @Override
    public String rPop(String key) {
        log.info("阿里云Redis List右弹出成功: key={}", key);
        return "mock_list_value";
    }

    @Override
    public long lLen(String key) {
        log.info("阿里云Redis List长度获取成功: key={}", key);
        return 3L;
    }

    @Override
    public List<String> lRange(String key, long start, long end) {
        log.info("阿里云Redis List范围获取成功: key={}, start={}, end={}", key, start, end);
        List<String> result = new ArrayList<>();
        result.add("item1");
        result.add("item2");
        result.add("item3");
        return result;
    }

    @Override
    public String lIndex(String key, long index) {
        log.info("阿里云Redis List索引获取成功: key={}, index={}", key, index);
        return "mock_item_" + index;
    }

    @Override
    public boolean lSet(String key, long index, String value) {
        log.info("阿里云Redis List索引设置成功: key={}, index={}, value={}", key, index, value);
        return true;
    }

    @Override
    public long lRem(String key, long count, String value) {
        log.info("阿里云Redis List移除成功: key={}, count={}, value={}", key, count, value);
        return Math.abs(count);
    }

    // Set 操作
    @Override
    public long sAdd(String key, String... members) {
        log.info("阿里云Redis Set添加成功: key={}, members={}", key, Arrays.toString(members));
        return members.length;
    }

    @Override
    public long sRem(String key, String... members) {
        log.info("阿里云Redis Set移除成功: key={}, members={}", key, Arrays.toString(members));
        return members.length;
    }

    @Override
    public boolean sIsMember(String key, String member) {
        log.info("阿里云Redis Set成员检查成功: key={}, member={}", key, member);
        return true;
    }

    @Override
    public Set<String> sMembers(String key) {
        log.info("阿里云Redis Set成员获取成功: key={}", key);
        Set<String> result = new HashSet<>();
        result.add("member1");
        result.add("member2");
        result.add("member3");
        return result;
    }

    @Override
    public long sCard(String key) {
        log.info("阿里云Redis Set基数获取成功: key={}", key);
        return 3L;
    }

    @Override
    public Set<String> sInter(String... keys) {
        log.info("阿里云Redis Set交集获取成功: keys={}", Arrays.toString(keys));
        Set<String> result = new HashSet<>();
        result.add("common_member");
        return result;
    }

    @Override
    public Set<String> sUnion(String... keys) {
        log.info("阿里云Redis Set并集获取成功: keys={}", Arrays.toString(keys));
        Set<String> result = new HashSet<>();
        result.add("member1");
        result.add("member2");
        result.add("member3");
        return result;
    }

    @Override
    public Set<String> sDiff(String... keys) {
        log.info("阿里云Redis Set差集获取成功: keys={}", Arrays.toString(keys));
        Set<String> result = new HashSet<>();
        result.add("diff_member");
        return result;
    }

    // ZSet 操作
    @Override
    public long zAdd(String key, double score, String member) {
        log.info("阿里云Redis ZSet添加成功: key={}, score={}, member={}", key, score, member);
        return 1L;
    }

    @Override
    public long zRem(String key, String... members) {
        log.info("阿里云Redis ZSet移除成功: key={}, members={}", key, Arrays.toString(members));
        return members.length;
    }

    @Override
    public double zScore(String key, String member) {
        log.info("阿里云Redis ZSet分数获取成功: key={}, member={}", key, member);
        return 100.0;
    }

    @Override
    public long zCard(String key) {
        log.info("阿里云Redis ZSet基数获取成功: key={}", key);
        return 5L;
    }

    @Override
    public Set<String> zRange(String key, long start, long end) {
        log.info("阿里云Redis ZSet范围获取成功: key={}, start={}, end={}", key, start, end);
        Set<String> result = new LinkedHashSet<>();
        result.add("member1");
        result.add("member2");
        result.add("member3");
        return result;
    }

    @Override
    public Set<String> zRevRange(String key, long start, long end) {
        log.info("阿里云Redis ZSet反向范围获取成功: key={}, start={}, end={}", key, start, end);
        Set<String> result = new LinkedHashSet<>();
        result.add("member3");
        result.add("member2");
        result.add("member1");
        return result;
    }

    @Override
    public Set<String> zRangeByScore(String key, double min, double max) {
        log.info("阿里云Redis ZSet分数范围获取成功: key={}, min={}, max={}", key, min, max);
        Set<String> result = new LinkedHashSet<>();
        result.add("member1");
        result.add("member2");
        return result;
    }

    @Override
    public Set<String> zRevRangeByScore(String key, double max, double min) {
        log.info("阿里云Redis ZSet反向分数范围获取成功: key={}, max={}, min={}", key, max, min);
        Set<String> result = new LinkedHashSet<>();
        result.add("member2");
        result.add("member1");
        return result;
    }

    // 事务操作
    @Override
    public void multi() {
        log.info("阿里云Redis事务开始成功");
    }

    @Override
    public void exec() {
        log.info("阿里云Redis事务执行成功");
    }

    @Override
    public void discard() {
        log.info("阿里云Redis事务丢弃成功");
    }

    // 管道操作
    @Override
    public void pipeline() {
        log.info("阿里云Redis管道开始成功");
    }

    @Override
    public void sync() {
        log.info("阿里云Redis管道同步成功");
    }

    // Lua脚本
    @Override
    public Object eval(String script, List<String> keys, List<String> args) {
        log.info("阿里云Redis Lua脚本执行成功: script={}, keys={}, args={}", script, keys, args);
        return "script_result";
    }

    // 键管理
    @Override
    public Set<String> keys(String pattern) {
        log.info("阿里云Redis键模式匹配成功: pattern={}", pattern);
        Set<String> result = new HashSet<>();
        result.add("key1");
        result.add("key2");
        result.add("key3");
        return result;
    }

    @Override
    public String type(String key) {
        log.info("阿里云Redis键类型获取成功: key={}", key);
        return "string";
    }

    @Override
    public long memoryUsage(String key) {
        log.info("阿里云Redis内存使用获取成功: key={}", key);
        return 1024L;
    }

    // 数据库管理
    @Override
    public boolean flushAll() {
        log.info("阿里云Redis清空所有数据库成功");
        return true;
    }

    @Override
    public boolean flushDB() {
        log.info("阿里云Redis清空当前数据库成功");
        return true;
    }

    // 连接管理
    @Override
    public boolean ping() {
        log.info("阿里云Redis连接测试成功");
        return true;
    }

    @Override
    public void close() {
        log.info("阿里云Redis连接关闭成功");
    }

    @PreDestroy
    public void destroy() {
        log.info("阿里云Redis服务销毁成功");
        close();
    }
}